package com.tee.live.im.core.server.handler;

import com.alibaba.fastjson.JSON;
import com.tee.im.constants.ImConstants;
import com.tee.im.constants.ImMsgCodeEnum;
import com.tee.im.dto.ImMsgBody;
import com.tee.live.framework.redis.starter.key.ImCoreServerProviderCacheKeyBuilder;
import com.tee.live.im.core.server.common.ImContextUtils;
import com.tee.live.im.core.server.common.ImMsg;
import io.netty.channel.ChannelHandlerContext;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 心跳消息处理器
 *
 * @author tee
 * @date 2025/10/22
 */
@Component
public class HeartBeatImMsgHandler implements SimplyHandler {

    private static final Logger log = LoggerFactory.getLogger(HeartBeatImMsgHandler.class);
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ImCoreServerProviderCacheKeyBuilder cacheKeyBuilder;

    @Override
    public void handler(ChannelHandlerContext ctx, ImMsg imMsg) {
        // 心跳消息处理
        Long userId = ImContextUtils.getUserId(ctx);
        Integer appId = ImContextUtils.getAppId(ctx);
        if (userId == null || appId == null) {
            log.error("attr error,imMsg is {}", imMsg);
            throw new IllegalArgumentException("attr is error");
        }

        // 构建心跳缓存
        String redisKey = cacheKeyBuilder.buildImLoginTokenKey(userId, appId);
        this.recordOnlineTime(userId, redisKey);
        this.removeExpireRecord(redisKey);
        redisTemplate.expire(redisKey, 5, TimeUnit.MINUTES);
        ImMsgBody imMsgBody = new ImMsgBody();
        imMsgBody.setAppId(appId);
        imMsgBody.setUserId(userId);
        imMsgBody.setData("true");
        ImMsg respMsg = ImMsg.build(ImMsgCodeEnum.IM_HEARTBEAT_MSG.getCode(), JSON.toJSONString(imMsgBody));
        log.info("[heartbeatImMsgHandler] imMsg is {}", imMsg);
        ctx.writeAndFlush(respMsg);
    }

    private void removeExpireRecord(final String redisKey) {

        redisTemplate.opsForZSet()
            .removeRangeByScore(redisKey, 0, System.currentTimeMillis() - ImConstants.DEFAULT_HEART_BEAT_GAP * 2);
    }

    /**
     * 记录用户最近一次心跳时间到zset上
     *
     * @param userId
     * @param redisKey
     */
    private void recordOnlineTime(final Long userId, final String redisKey) {

        redisTemplate.opsForZSet()
            .add(redisKey, userId, System.currentTimeMillis());

    }

}
